package cn.signalpha.modules.system.service.impl;


import cn.signalpha.common.cache.ParamCache;
import cn.signalpha.common.cache.SysCache;
import cn.signalpha.common.cache.UserCache;
import cn.signalpha.common.constant.CommonConstant;
import cn.signalpha.core.log.exception.ServiceException;
import cn.signalpha.core.mp.base.BaseServiceImpl;
import cn.signalpha.core.secure.utils.AuthUtil;
import cn.signalpha.core.tool.constant.SystemConstant;
import cn.signalpha.core.tool.utils.*;
import cn.signalpha.modules.auth.dto.UserInfo;
import cn.signalpha.modules.system.entity.User;
import cn.signalpha.modules.system.entity.UserDept;
import cn.signalpha.modules.system.excel.UserExcel;
import cn.signalpha.modules.system.mapper.UserMapper;
import cn.signalpha.modules.system.service.IRoleService;
import cn.signalpha.modules.system.service.IUserDeptService;
import cn.signalpha.modules.system.service.IUserService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static cn.signalpha.common.constant.CommonConstant.DEFAULT_PARAM_PASSWORD;

/**
 * 服务实现类
 */
@Service
@AllArgsConstructor
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements IUserService {
	private static final String GUEST_NAME = "guest";

	private final IUserDeptService userDeptService;
	private final IRoleService roleService;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean submit(User user) {
		if (Func.isNotEmpty(user.getPassword())) {
			user.setPassword(DigestUtil.encrypt(user.getPassword()));
		}
		Long accountCount = baseMapper.selectCount(Wrappers.<User>query().lambda().eq(User::getAccount, user.getAccount()));
		if (accountCount > 0 && Func.isEmpty(user.getId())) {
			throw new ServiceException(StringUtil.format("当前账号 [{}] 已存在!", user.getAccount()));
		}
		Long phoneCount = baseMapper.selectCount(Wrappers.<User>query().lambda().eq(User::getPhone, user.getPhone()));
		if (phoneCount > 0 && Func.isEmpty(user.getId())) {
			throw new ServiceException(StringUtil.format("当前手机号 [{}] 已存在!", user.getPhone()));
		}
		return save(user) && submitUserDept(user);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean updateUser(User user) {
		Long accountCount = baseMapper.selectCount(
			Wrappers.<User>query().lambda()
				.eq(User::getAccount, user.getAccount())
				.notIn(User::getId, user.getId())
		);
		if (accountCount > 0) {
			throw new ServiceException(StringUtil.format("当前账号 [{}] 已存在!", user.getAccount()));
		}
		Long phoneCount = baseMapper.selectCount(
			Wrappers.<User>query().lambda()
				.eq(User::getPhone, user.getPhone())
				.notIn(User::getId, user.getId())
		);
		if (phoneCount > 0) {
			throw new ServiceException(StringUtil.format("当前手机号 [{}] 已存在!", user.getPhone()));
		}
		return updateUserInfo(user) && submitUserDept(user);
	}

	@Override
	public boolean updateUserInfo(User user) {
		user.setPassword(null);
		return updateById(user);
	}

	private boolean submitUserDept(User user) {
		List<Long> deptIdList = Func.toLongList(user.getDeptId());
		List<UserDept> userDeptList = new ArrayList<>();
		deptIdList.forEach(deptId -> {
			UserDept userDept = new UserDept();
			userDept.setUserId(user.getId());
			userDept.setDeptId(deptId);
			userDeptList.add(userDept);
		});
		userDeptService.remove(Wrappers.<UserDept>update().lambda().eq(UserDept::getUserId, user.getId()));
		return userDeptService.saveBatch(userDeptList);
	}

	@Override
	public IPage<User> selectUserPage(IPage<User> page, User user, Long deptId) {
		List<Long> deptIdList = SysCache.getDeptChildIds(deptId);
		return page.setRecords(baseMapper.selectUserPage(page, user, deptIdList));
	}

	@Override
	public User userByAccount(String account) {
		return baseMapper.selectOne(Wrappers.<User>query().lambda().eq(User::getAccount, account).eq(User::getIsDeleted, SystemConstant.DB_NOT_DELETED));
	}

	@Override
	public UserInfo userInfo(Long userId) {
		User user = baseMapper.selectById(userId);
		return buildUserInfo(user);
	}

	@Override
	public UserInfo userInfo(String account, String password) {
		User user = baseMapper.getUser(account, password);
		return buildUserInfo(user);
	}

	private UserInfo buildUserInfo(User user) {
		if (ObjectUtil.isEmpty(user)) {
			return null;
		}
		UserInfo userInfo = Objects.requireNonNull(BeanUtil.copy(user, UserInfo.class));
		userInfo.setNickName(user.getName());
		userInfo.setRoles(roleService.getRoleAliases(user.getRoleId()));
		return userInfo;
	}

	@Override
	public boolean grant(String userIds, String roleIds) {
		User user = new User();
		user.setRoleId(roleIds);
		return this.update(user, Wrappers.<User>update().lambda().in(User::getId, Func.toLongList(userIds)));
	}

	@Override
	public boolean resetPassword(String userIds) {
		User user = new User();
		user.setPassword(DigestUtil.encrypt(CommonConstant.DEFAULT_PASSWORD));
		user.setUpdateTime(DateUtil.now());
		return this.update(user, Wrappers.<User>update().lambda().in(User::getId, Func.toLongList(userIds)));
	}

	@Override
	public boolean updatePassword(Long userId, String oldPassword, String newPassword, String newPassword1) {
		User user = getById(userId);
		if (!newPassword.equals(newPassword1)) {
			throw new ServiceException("请输入正确的确认密码!");
		}
		if (!user.getPassword().equals(DigestUtil.hex(oldPassword))) {
			throw new ServiceException("原密码不正确!");
		}
		return this.update(Wrappers.<User>update().lambda().set(User::getPassword, DigestUtil.hex(newPassword)).eq(User::getId, userId));
	}

	@Override
	public boolean removeUser(String userIds) {
		if (Func.contains(Func.toLongArray(userIds), AuthUtil.getUserId())) {
			throw new ServiceException("不能删除本账号!");
		}
		return deleteLogic(Func.toLongList(userIds));
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void importUser(List<UserExcel> data, Boolean isCovered) {
		data.forEach(userExcel -> {
			User user = Objects.requireNonNull(BeanUtil.copy(userExcel, User.class));
			// 设置部门ID
			user.setDeptId(Func.toStrWithEmpty(SysCache.getDeptIds(userExcel.getDeptName()), StringPool.EMPTY));
			// 设置角色ID
			user.setRoleId(Func.toStrWithEmpty(SysCache.getRoleIds(userExcel.getRoleName()), StringPool.EMPTY));
			// 覆盖数据
			if (isCovered) {
				// 查询用户是否存在
				User oldUser = UserCache.getUser(userExcel.getAccount());
				if (oldUser != null && oldUser.getId() != null) {
					user.setId(oldUser.getId());
					this.updateUser(user);
					return;
				}
			}
			// 获取默认密码配置
			String initPassword = ParamCache.getValue(DEFAULT_PARAM_PASSWORD);
			user.setPassword(initPassword);
			this.submit(user);
		});
	}

	@Override
	public List<UserExcel> exportUser(Wrapper<User> queryWrapper) {
		List<UserExcel> userList = baseMapper.exportUser(queryWrapper);
		userList.forEach(user -> {
			user.setRoleName(StringUtil.join(SysCache.getRoleNames(user.getRoleId())));
			user.setDeptName(StringUtil.join(SysCache.getDeptNames(user.getDeptId())));
		});
		return userList;
	}

}
